﻿// JUZHISDK.cpp : 定义静态库的函数。
//

#include "pch.h"
#include "JUZHISDK.h"
#include "framework.h"
#include "tools.h"
#include "CCjs.h"
#include "rapidjson/document.h"
#include <iostream>

JuZhiSDK::JuZhiSDK(const wchar_t* n)
{
	try
	{
		auto script = LoadFile(n);
		ccjs.RunScript(script.c_str());
	}
	catch (const ChakraErrorException& e)
	{
		char  str[100]{ 0 };
		sprintf_s(str, "%X\n", e.GetErrorCode());
		return;
	}
	return;
}

JuZhiSDK::~JuZhiSDK()
{
}

std::string JuZhiSDK::Rsa(std::string data, std::string pubkey) {
	try
	{
		auto func = ccjs.GetObjectAsProperty(L"crypt");
		JsValueRef callbackArgs[] = {
			ccjs.GetGlobal(),
			Vconvert(data),
			Vconvert(pubkey)
		};

		JsValueRef 	   result;
		JsCallFunction(func, callbackArgs, sizeof(callbackArgs) / sizeof(JsValueRef), &result);

		const wchar_t* resultWC;
		size_t stringLength;
		JsStringToPointer(result, &resultWC, &stringLength);

		return string_convert::UnicodeToANSI(resultWC);
	}
	catch (const ChakraErrorException& e)
	{
		printf("%d\n", e.GetErrorCode());
	}
	return "";
}

std::string JuZhiSDK::Md5(std::string data) {
	try
	{
		auto func = ccjs.GetObjectAsProperty(L"mymd5");
		JsValueRef callbackArgs[] = {
			ccjs.GetGlobal(),
			Vconvert(data)
		};

		JsValueRef 	   result;
		JsCallFunction(func, callbackArgs, sizeof(callbackArgs) / sizeof(JsValueRef), &result);

		const wchar_t* resultWC;
		size_t stringLength;
		JsStringToPointer(result, &resultWC, &stringLength);

		return string_convert::UnicodeToANSI(resultWC);
	}
	catch (const ChakraErrorException& e)
	{
		printf("%d\n", e.GetErrorCode());
	}
	return "";
}


std::string JuZhiSDK::Base64(std::string data) {
	try
	{
		auto func = ccjs.GetObjectAsProperty(L"bsae64decode");
		JsValueRef callbackArgs[] = {
			ccjs.GetGlobal(),
			Vconvert(data)
		};

		JsValueRef 	   result;
		JsCallFunction(func, callbackArgs, sizeof(callbackArgs) / sizeof(JsValueRef), &result);

		const wchar_t* resultWC;
		size_t stringLength;
		JsStringToPointer(result, &resultWC, &stringLength);

		return string_convert::UnicodeToANSI(resultWC);
	}
	catch (const ChakraErrorException& e)
	{
		printf("%d\n", e.GetErrorCode());
	}
	return "";
}

cpr::Payload JuZhiSDK::PackRequest(std::string enc_buff, std::string api_name) {
	std::string time = convert<std::string>(getTimeStamp(true));
	return cpr::Payload{
		{"appid",APPID},
		{"api",api_name},
		{"timestamp",time},
		{"data",enc_buff},
		{"sign", Md5(APPID + api_name + SIGNKEY + time + enc_buff)}
	};
}

std::string JuZhiSDK::RequestData(std::string buff, std::string api_name) {

	auto enc_buff = Rsa(buff, RSAKEY);
	cpr::Response r = cpr::Post(
		cpr::Url{ URL },
		PackRequest(enc_buff, api_name)
	);
	if (r.status_code != 200)
	{
		return "";
	}
	rapidjson::Document json;
	json.Parse(r.text.c_str());
	std::string code = json["code"].GetString();
	if (code != "1")
	{
		error_msg = string_convert::UTF8ToANSI(json["msg"].GetString());
		return "";
	}
	return Base64(json["data"].GetString()).c_str();
}

bool JuZhiSDK::AppInit() {
	auto res = RequestData("appkey=" + APPKEY + "&verid=" + VERID, "App_Preset");
	if (res == "")
	{
		return false;
	}
	rapidjson::Document json;
	json.Parse(res.c_str());
	LastVer = json["LastVer"].GetString();
	Bulletin = json["Bulletin"].GetString();
	Update = json["Update"].GetBool();
	AppMd5 = json["Md5"].GetString();
	return true;
}

bool JuZhiSDK::UserLogin(std::string user, std::string pwd, std::string mac) {
	auto res = RequestData(
		"appkey=" + APPKEY +
		"&user=" + user +
		"&pwd=" + Md5(pwd) +
		"&mac=" + Md5(mac) +
		"&verid=" + VERID
		, "User_Login");
	if (res == "")
	{
		return false;
	}
	rapidjson::Document json;
	json.Parse(res.c_str());
	Token = json["Token"].GetString();
	Finaltime = json["Finaltime"].GetString();
	Tally = json["Tally"].GetInt();
	Sign = json["Sign"].GetInt();

	ThisUser = user;
	return true;
}


bool JuZhiSDK::UserRegister(std::string user, std::string pwd, std::string email, std::string mac) {
	auto res = RequestData(
		"appkey=" + APPKEY +
		"&user=" + user +
		"&pwd=" + Md5(pwd) +
		"&mac=" + Md5(mac) +
		"&email=" + email
		, "User_Create");
	if (res == "")
	{
		return false;
	}
	rapidjson::Document json;
	json.Parse(res.c_str());
	sucess_msg = json["Msg"].GetString();
	return true;
}

bool JuZhiSDK::UserUnBind(std::string user, std::string pwd, std::string mac, std::string type) {

	auto res = RequestData(
		"appkey=" + APPKEY + "&user=" + user + "&pwd=" + Md5(pwd) +
		"&type=" + type + "&bind=1&mac=" + Md5(mac),
		"User_Change");
	if (res == "")
	{
		return false;
	}
	rapidjson::Document json;
	json.Parse(res.c_str());
	Finaltime = json["Finaltime"].GetString();
	Tally = json["Tally"].GetInt();
	Deduct = json["Deduct"].GetInt();
	return true;
}

bool JuZhiSDK::UserRecharge(std::string user, std::string card) {
	auto res = RequestData(
		"appkey=" + APPKEY + "&user=" + user + "&cdkey=" + card,
		"User_Recharge");
	if (res == "")
	{
		return false;
	}
	rapidjson::Document json;
	json.Parse(res.c_str());

	Finaltime = json["Finaltime"].GetString();
	Tally = json["Tally"].GetInt();
	return true;
}

bool JuZhiSDK::UserChangepwd(std::string user, std::string npwd, std::string email) {
	auto res = RequestData(
		"appkey=" + APPKEY + "&user=" + user + "&npwd=" + Md5(npwd) + "&email=" + email,
		"Change_Pwd");
	if (res == "")
	{
		return false;
	}
	rapidjson::Document json;
	json.Parse(res.c_str());
	sucess_msg = json["Msg"].GetString();
	return true;
}

bool JuZhiSDK::GetUserStatus() {
	auto res = RequestData(
		"appkey=" + APPKEY + "&user=" + ThisUser + "&token=" + Token,
		"Get_User_Status");
	if (res == "")
	{
		return false;
	}
	rapidjson::Document json;
	json.Parse(res.c_str());
	Token = json["NewToken"].GetString();
	return true;
}


bool JuZhiSDK::UserCdkeyLogin(std::string card, std::string mac) {
	auto res = RequestData(
		"appkey=" + APPKEY + "&cdkey=" + card + "&mac=" + Md5(mac) + "&verid=" + VERID,
		"Cdkey_login");
	if (res == "")
	{
		return false;
	}
	rapidjson::Document json;
	json.Parse(res.c_str());
	Token = json["Token"].GetString();
	Finaltime = json["Finaltime"].GetString();
	Tally = json["Tally"].GetInt();
	Sign = json["Sign"].GetInt();

	ThisUser = card;
	return true;
}

std::shared_ptr<JuZhiSDK>& GetSdkInstance(const wchar_t* n) {
	static std::shared_ptr<JuZhiSDK> sdk = nullptr;
	if (sdk == nullptr)
	{
		sdk = std::make_shared<JuZhiSDK>(n);
	}
	return sdk;
}